package com.link.base.base.billstatementparam.service;

import com.link.base.base.accnt.service.AccountService;
import com.link.base.base.billstatementparam.dao.mybatis.mapper.BillStatementParamMapper;
import com.link.base.base.billstatementparam.model.BillStatementParam;
import com.link.base.base.enterprise.service.EnterpriseService;
import com.link.base.base.fund.dao.mybatis.mapper.BillAccountMapper;
import com.link.base.base.fund.model.BillAccount;
import com.link.base.base.fund.model.BillAccountDetail;
import com.link.base.base.fund.model.BillDetailModel;
import com.link.base.base.fund.model.DealerTransactionDetail;
import com.link.base.base.fund.service.BillAccountDetailService;
import com.link.base.base.fund.service.DealerAccountService;
import com.link.base.base.fund.service.DealerTransactionDetailService;
import com.link.core.cllog.LCLogger;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.ServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.KeyGenerateService;
import com.link.core.util.DateUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * Copyright  hande Company. All Rights Reserved.
 *
 * @author crm4
 * @version 1.0
 * @date: 2018-06-22
 */

@Service
public class BillStatementParamServiceImpl extends BasicServiceImpl<BillStatementParam> implements BillStatementParamService {

    /**
     * 企业
     */
    @Resource
    public EnterpriseService enterpriseService;
    /**
     * 客户
     */
    @Resource
    public AccountService accountService;
    /***
     * 资金账户
     */
    @Resource
    public DealerAccountService dealerAccountService;
    /**
     * 交易明细
     */
    @Resource
    public DealerTransactionDetailService dealerTransactionDetailService;
    @Resource
    public BillAccountDetailService billAccountDetailService;
    @Resource
    public KeyGenerateService keyGenerateService;
    @Resource
    private BillStatementParamMapper billStatementParamMapper;
    @Resource
    private BillAccountMapper billAccountMapper;

    @Override
    public BasicMapper<BillStatementParam> getBasicMapper() {
        return billStatementParamMapper;
    }

    /**
     * 查询有效的对账订单参数
     *
     * @param billStatementParam 企业开启对账单开关
     *                           对账单参数为指定预定时间
     *                           非运行状态
     * @return
     * @throws Exception
     */
    @Override
    public List<BillStatementParam> queryAllValidBillState(BillStatementParam billStatementParam) throws Exception {
        return billStatementParamMapper.queryAllValidBillState(billStatementParam);
    }

    /***
     * 生成对账单
     * 因该出需要手动和定时两者调用，所以抽到业务层
     * 但是该方法中的业务操作不是同事务原子操作，所以不需要保证整体成功
     * @param billStatementParam  对账单参数对象
     *                         传入的参数必须包含以下四个查询条件值
     *                         必须
    billStatementParam.setAttr1("Y");  //企业对单开关
    billStatementParam.setCloseFlag("N");  //是否运行状态
    billStatementParam.setPreRunStartDate(DateUtil.dateToStr(new Date(), "yyyy-MM-dd"));  //预运行时间
    billStatementParam.setPageFlag(false);  //不分页
    可选   可以具体到某个企业下的某个对账单参数区间
    billStatementParam.setCorpid(""); //账套设置 具体到某个企业
    billStatementParam.setId("");  //对账单参数id
     * @throws Exception
     */
    @Override
    public String[] billAccntCreateALL(BillStatementParam billStatementParam) throws Exception {
        /**
         * 获取到指定条件下交易明细
         * 期间参数id = 对账单期间id
         */
        //查询符合要求的客户
        //遍历  查询 指定id 和期间id  查看是否存在对账单头
        // 如果存在   就更新
        //如果不存在 就创建 对账单头  并根据期间范围内的交易明细创建 对账单明细
        List<BillStatementParam> billStateList = queryAllValidBillState(billStatementParam);
        billStateList.stream().forEach(e -> {
            try {
                BillDetailModel b = new BillDetailModel();
                b.setPageFlag(false);
                //企业对账单开启
                b.setBillStatFlag("Y");
                //客户状态有效
                b.setAcctStatus("Y");
                //客户开启对账单开关
                b.setAccntStateFlag("Y");
                //对账单参数 非运行
                b.setBillStateCloseFlag("N");
                //预计运行时间 当前系统日期
                b.setBillStatePreRunStartDate(DateUtil.dateToStr(new Date(), "yyyy-MM-dd"));
                b.setCorpid(e.getCorpid());
                //客户处理
                handlerBatchBillState(b);
                e.setCloseFlag("Y");
                e.setSuccessFlag("Y");

            } catch (Exception e1) {
                LCLogger.withException(e1);
                e.setCloseFlag("N");
                e.setSuccessFlag("N");
            }
            try {
                e.setActualRunDate(DateUtil.dateToStr(new Date(), "yyyy-MM-dd HH:mm:ss"));
                update(e);
            } catch (Exception e1) {
                LCLogger.withException(e1);
                throw new ServiceException(e1.getMessage());
            }
        });
        return null;
    }


    /**
     * 客户处理
     * 生成对账单头和行
     *
     * @param billDetailModel
     * @throws Exception
     */
    public void handlerBatchBillState(BillDetailModel billDetailModel) throws Exception {
        List<BillDetailModel> accounts = null;
        accounts = accountService.queryAllBillAccntByCondtion(billDetailModel);
        accounts.stream().forEach(accnt -> {
            //查找指定客户下的对账单
            BillAccount condtionBA = new BillAccount();
            condtionBA.setLoginCorpId(accnt.getEnterpriseCode());
            condtionBA.setAccntId(accnt.getAccntId());
            condtionBA.setPeriodId(accnt.getPeriodId());
            List<BillAccount> baList = null;
            try {
                //查询存在的对账单
                baList = billAccountMapper.queryByCondtion(condtionBA);
                //对账单 不为空 更新
                if (!baList.isEmpty()) {
                    baList.stream().forEach(ba -> {
                        BillAccountDetail bad = new BillAccountDetail();
                        bad.setHeadId(ba.getId());
                        try {
                            //删除该下的所有对账单明细
                            billAccountDetailService.deleteByHeadId(bad);
                            //重新生成对账单明细
                            insertDealerTxnDet(accnt, ba);
                        } catch (Exception e) {
                            LCLogger.withException(e);
                            throw new ServiceException(e.getMessage());
                        }
                    });
                } else {
                    //新建
                    //生成对账单
                    Long nid = keyGenerateService.keyGenerate();
                    BillAccount nba = new BillAccount();
                    //主键
                    nba.setId(nid);
                    nba.setCorpid(accnt.getCorpid());
                    //客户id
                    nba.setAccntId(accnt.getAccntId());
                    //期间id
                    nba.setPeriodId(accnt.getPeriodId());
                    //是否确认
                    nba.setConfirmFlag("N");
                    nba.setConfirmDate(DateUtil.dateToStr(new Date(), "yyyy-MM-dd HH:mm:ss"));
                    billAccountMapper.insert(nba);
                    insertDealerTxnDet(accnt, nba);
                    /**
                     * @TODO
                     * 待添加新字段
                     * 是否生成 Y
                     * 发布时间  置空
                     * 是否发布 N
                     */
                }
            } catch (Exception e) {
                LCLogger.withException(e);
                throw new ServiceException(e.getMessage());
            }
        });
    }

    /***
     *  根据客户和对账单对象 生成或者更新对账单明细
     * @param accnt   符合生成对账单的客户
     * @param ba  对账单对象
     * @throws Exception
     */
    public void insertDealerTxnDet(BillDetailModel accnt, BillAccount ba) throws Exception {
        DealerTransactionDetail dealerTxnCond = new DealerTransactionDetail();
        dealerTxnCond.setPageFlag(false);
        //客户id
        dealerTxnCond.setAccntId(accnt.getAccntId());
        //期间  开始时间
        dealerTxnCond.setAttr1(accnt.getPeriodStartDate());
        //期间  结束时间
        dealerTxnCond.setAttr2(accnt.getPeriodEndDate());
        //交易明细
        List<DealerTransactionDetail> list = dealerTransactionDetailService.queryByPeriod(dealerTxnCond);
        list.stream().forEach(dealer -> {
            BillAccountDetail nbad = new BillAccountDetail();
            nbad.setHeadId(ba.getId());
            //交易明细corp
            nbad.setCorpid(dealer.getCorpid());
            //资金账户id
            nbad.setAccntId(dealer.getHeadId());
            nbad.setAmount(dealer.getAmount());
            nbad.setDealTime(dealer.getDealTime());
            nbad.setSourceNum(dealer.getSourceNum());
            nbad.setSourceType(dealer.getSourceType());
            nbad.setTextDigest(dealer.getTextDigest());
            try {
                billAccountDetailService.insert(nbad);
            } catch (Exception e) {
                LCLogger.withException(e);
                throw new ServiceException(e.getMessage());
            }
        });
    }
}
